package com.kool.kreport.client;

import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author : luyu
 * @date :2021/3/26 13:38
 */
@Component
public class RedisClient {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 赋值
     * KV结构
     *
     * @param key
     * @param value
     */
    public void set(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    /**
     * 赋值，自动过期删除，时间单位：毫秒
     * KV结构
     *
     * @param key
     * @param value
     * @param timeout
     */
    public void set(String key, String value, long timeout) {
        stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.MILLISECONDS);
    }

    /**
     * 取值
     * KV结构
     *
     * @param key
     * @return
     */
    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * 删除key
     *
     * @param key
     */
    public void delete(String key) {
        stringRedisTemplate.delete(key);
    }

    /**
     * 设置key过期时间，单位毫秒
     *
     * @param key
     * @param timeout
     */
    public void expire(String key, long timeout) {
        stringRedisTemplate.expire(key, timeout, TimeUnit.MILLISECONDS);
    }

    /**
     * 赋值
     * HASH结构
     *
     * @param hash
     * @param key
     * @param value
     */
    public void hput(String hash, String key, String value) {
        HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
        hashOperations.put(hash, key, value);
    }

    /**
     * 批量赋值
     * HASH结构
     *
     * @param hash
     * @param map
     */
    public void hputAll(String hash, Map<String, String> map) {
        HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
        hashOperations.putAll(hash, map);
    }

    /**
     * 取值
     * HASH结构
     *
     * @param hash
     * @param key
     * @return
     */
    public String hget(String hash, String key) {
        HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
        return hashOperations.get(hash, key);
    }

    /**
     * 取hash
     * HASH结构
     *
     * @param hash
     * @return
     */
    public Map<String, String> hgetMap(String hash) {
        HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
        return hashOperations.entries(hash);
    }

    /**
     * 自增1
     * KV结构
     *
     * @param key
     * @return
     */
    public long inrc(String key) {
        Long l = stringRedisTemplate.opsForValue().increment(key);
        if (l == null) {
            stringRedisTemplate.opsForValue().set(key, "1");
            return 1L;
        }
        return l;
    }

    /**
     * 自增1，自动过期，单位：毫秒
     * KV结构
     *
     * @param key
     * @param timeout
     * @return
     */
    public long inrc(String key, long timeout) {
        Long l = stringRedisTemplate.opsForValue().increment(key);
        if (l == null) {
            stringRedisTemplate.opsForValue().set(key, "1");
            return 1L;
        }
        stringRedisTemplate.expire(key, timeout, TimeUnit.MILLISECONDS);
        return l;
    }

    /**
     * 自增1，自动过期，单位：毫秒
     * KV结构
     *
     * @param key
     * @param delta
     * @param timeout
     * @return
     */
    public long inrc(String key, long delta, long timeout) {
        Long l = stringRedisTemplate.opsForValue().increment(key, delta);
        if (l == null) {
            stringRedisTemplate.opsForValue().set(key, Long.toString(delta));
            return 1L;
        }
        stringRedisTemplate.expire(key, timeout, TimeUnit.MILLISECONDS);
        return l;
    }

    /**
     * key是否存在
     *
     * @param key
     * @return
     */
    public boolean hasKey(String key) {
        return stringRedisTemplate.hasKey(key);
    }

    /**
     * scan方法获取key集合
     *
     * @param matchKey
     * @return
     */
    public Set<String> scan(String matchKey) {
        Set<String> keys = stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> {
            Set<String> keysTmp = new HashSet<>();
            Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(matchKey).count(1000).build());
            while (cursor.hasNext()) {
                keysTmp.add(new String(cursor.next()));
            }
            return keysTmp;
        });

        return keys;
    }
}
